<?php
/**
 * Product
 *
 * Обработка данных товаров
 *
 * @author Mike
 */
class Product extends ActiveRecord  {
	protected $tableName = 'product';
	public $pkName = 'ID_product';
	
	public static $idEssenceType = 1;
	
	protected $arrWysiwyg = array('description');
	
	// Допустимые типы размеров продуктов
	public static $availableSizeTypes = array(
			1 => 'Обувь',
			2 => 'Штаны/Джинсы',
			3 => 'Стандартный'
	);
	
	protected $arrSettings = array('created_at' => true, 'author' => true, 'updated_at' => true);

	public $validatesLengthOf = array(
			'product_name' => array('min' => 2, 'max' => 256, 'message' => 'Название - 2-256 символов'),
			'description' => array('min' => 2, 'max' => 1024, 'message' => 'Описание - 2-1024 символов'),
			'url' => array('min' => 1, 'max' => 64, 'message' => 'URL - от 1 до 64 символов'),
	);
	
	public $validatesFormatOf = array(
			'url' => array('with' => '/^[\-_a-z0-9\.]+$/ui', 'message' => 'URL заполнен неверно'),
			'our_price' => array('with' => '#^[0-9]{1,5}$#ui', 'message' => 'Наша цена заполнена неверно'),
			'client_price' => array('with' => '#^[0-9]{1,5}$#ui', 'message' => 'Цена клиента заполнена неверно'),
			'wordstat_simple' => array('with' => '#^[0-9]{1,7}$#ui', 'message' => 'wordstat_simple заполнен неверно', 'allowNull' => true),
			'wordstat_buy' => array('with' => '#^[0-9]{1,7}$#ui', 'message' => 'wordstat_buy заполнен неверно', 'allowNull' => true),
			'wordstat_price' => array('with' => '#^[0-9]{1,7}$#ui', 'message' => 'wordstat_price заполнен неверно', 'allowNull' => true)
	);
	
	public $validatesUniquenessOf = array(
			'url' => array('message' => 'Такой URL уже используется')
	);
	
	public function beforeValidation() {
		if(!empty($this->tableFields['ID_category'])) {
			$arrAvailableCategoriesIds = $this->getCategoriesAvailableForLink();
			if(!array_key_exists($this->getField('ID_category'), $arrAvailableCategoriesIds)) $this->errorValidated('', 'Недопустимая категория');
		}
		
		// Переписываем в отдельный атрибут дополнительные свойства товара, которые будем сохранять после самого сохранения товара, чтобы они не мешали сохранению объекта
		$arrAvailablePropertiesValues = ProductProperty::getAllPropertiesValueIds();
		$arrYetUsedProperties = array();	// Массив id свойств, для которых уже было добавлено одно значение. В рамках одного свойства нельзя добавлять более одного значения
		
		$this->properties = array();
		foreach($this->tableFields as $field => $value) {
			preg_match('#prod_prop([0-9]{1,5})#', $field, $arrMatches);
			$idPropertyValue = isset($arrMatches[1]) ? intval($arrMatches[1]) : null;
			if($idPropertyValue && isset($arrAvailablePropertiesValues[$idPropertyValue])) {
				if(in_array($arrAvailablePropertiesValues[$idPropertyValue], $arrYetUsedProperties)) {
					$this->errorValidated('', 'В рамках одного свойства товара можно задать только одно значение');
					break;
				}
				$this->properties[] = $idPropertyValue;
				$arrYetUsedProperties[] = $arrAvailablePropertiesValues[$idPropertyValue];
				unset($this->tableFields[$field]);
			}
		}
	
	}
	
	public function afterSave() {
		$objDB = Service_Database::instanse();

		// Удаляем все записи о дополнительных свойствах и проставляем новые данные
		$objDB->delete('product_vs_property_value', array('ID_product' => $this->id));
		foreach($this->properties as $idProperty) {
			$objDB->insert('product_vs_property_value', array('ID_product_property_value' => $idProperty, 'ID_product' => $this->id));
		}
	}
	
	/**
	 * (non-PHPdoc)
	 * @see ActiveRecord::beforeSave()
	 */
	public function beforeSave() {
		if(!isset($this->tableFields['no_product'])) $this->tableFields['no_product'] = 0;
		else $this->tableFields['no_product'] = 1;
	}
	
	/**
	 * Метод получает категории, к которым можно привязывать товар
	 * Такие категории, которые не имеют дочерних категорий
	 */
	public function getCategoriesAvailableForLink() {
		$objDB = Service_Database::instanse();
		$stmt = 'SELECT `category`.*
				FROM `category`
				WHERE `category`.`ID_category` NOT IN
				(
					SELECT `category`.`ID_parent_category`
					FROM `category`
					WHERE `category`.`ID_parent_category` IS NOT NULL
				)';
		
		return Service_ArrayConverter::makeKeySimpleArrayFromMultyArray($objDB->select($stmt), 'ID_category', 'category_short_name');
	}
	
	/**
	 * Получает список всех возможных размеров для продукта с текущим типом размера
	 * 
	 */
	public function getAvailableSizes() {
		return Size::getSizesByType($this->getField('type'));
	}
	
	/**
	 * Получает отзывы для текущего товара
	 */
	public function getReviews() {
		$objDB = Service_Database::instanse();
		$stmt = "SELECT `review`.*, `user`.`first_name`, `user`.`is_admin`
				FROM `review`
				INNER JOIN `user` USING(`ID_user`)
				WHERE `review`.`ID_product` = '" . $this->id . "'
				ORDER BY `review`.`created_at` DESC";
		
		return $objDB->select($stmt);
	}
	
	/**
	 * Получаем список размеров, которые есть в наличии
	 */
	public function getSizesInActive() {
		$objDB = Service_Database::instanse();
		$stmt = "
			SELECT `product_active`.*, `size_name`
			FROM `product_active`
			INNER JOIN `size` USING(`ID_size`)
			WHERE `count` > 0 AND `ID_product` = '" . $this->id . "'
		";
		return $objDB->select($stmt);
	}
	
	/**
	 * Получает похожие товары
	 * 
	 * @pararm int $number - необходимое число похожих товаров
	 */
	public function getSimilarProducts($number) {
		$objDB = Service_Database::instanse();
		$arrSimilarProducts = array();
		
		$stmt = "SELECT `product`.*
				FROM `product`
				WHERE `product`.`ID_category` = '" . $this->getField('ID_category') . "'
				ORDER BY `product`.`product_name`";
		
		$arrProductsByIds = Service_ArrayConverter::makeKeyArrayFromMultyArray($objDB->select($stmt), 'ID_product');
		$productIds = array_keys($arrProductsByIds);
		$currentProductId = array_search($this->id, $productIds);

		for($i = $currentProductId + 1; $i < count($productIds); $i++) {
			$arrSimilarProducts[] = $arrProductsByIds[$productIds[$i]];
			if(count($arrSimilarProducts) == $number) break;
		}
		
		if(count($arrSimilarProducts) != $number) { 
			for($i = 0; $i < $currentProductId; $i++) {
				$arrSimilarProducts[] = $arrProductsByIds[$productIds[$i]];
				if(count($arrSimilarProducts) == $number) break;
			}
		}
		
		if(count($arrSimilarProducts) != $number) {
			$stmt = "SELECT `product`.*
				FROM `product`
				WHERE `product`.`ID_category` != '" . $this->getField('ID_category') . "'
				ORDER BY `product`.`product_name`
				LIMIT " . ($number - count($arrSimilarProducts));
			
			$arrSimilarProducts = array_merge($arrSimilarProducts, $objDB->select($stmt));
		}
			
		return $arrSimilarProducts;
	}
	
	/**
	 * Получает массив товаров разбитый по ID_category
	 * 
	 * @param array $arrExcludedIds - массив айдишников товаров, которые нужны исключить при получении
	 */
	public static function getProductsByCategoriesIds(array &$arrExcludedIds = array()) {
		$objDB = Service_Database::instanse();
		$stmt = "SELECT `product`.`ID_product`, `product`.`product_name`, `product`.`url`, `product`.`ID_category`, `category`.`category_short_name`
				FROM `product`
				LEFT JOIN `category` USING(`ID_category`)" .
				(!empty($arrExcludedIds) ? "WHERE `product`.`ID_product` NOT IN(" . implode(',', $arrExcludedIds) . ")" : '');
		
		$arrProducts = $objDB->select($stmt); 
		return Service_ArrayConverter::splitArrayByFields($arrProducts, array('ID_category'));
	}
}